package com.google.code.shardbatis.sharding.key;


import java.time.LocalDateTime;
import java.time.ZoneId;

//import com.baomidou.mybatisplus.toolkit.SystemClock;
//import com.google.code.shardbatis.sharding.exception.ShardingRuntimeException;
//import org.apache.commons.lang3.StringUtils;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//
//import java.lang.management.ManagementFactory;
//import java.net.InetAddress;
//import java.net.NetworkInterface;
//import java.time.LocalDateTime;
//import java.time.ZoneId;
//import java.util.concurrent.ThreadLocalRandom;
//
public class GhostKeyGenerator {
    //    private static final Logger logger = LoggerFactory.getLogger(GhostKeyGenerator.class);
//
    public static final long UNIX_BASE_DATE = LocalDateTime.of(1970, 1, 1, 0, 0, 0).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    //    /**
//     * 基础时间(一旦确定不能变动)
//     */
    public static final long EPOCH = LocalDateTime.of(2017, 1, 1, 0, 0, 0).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
//    /**
//     * 机器标识位数
//     */
//    private final long workerIdBits = 5L;
//    /**
//     * workerId最大值11111 -> 31
//     */
//    private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
//
//    /**
//     * 数据标识位数
//     */
//    private final long datacenterIdBits = 5L;
//    /**
//     * datacenterId最大值11111 -> 31
//     */
//    private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
//    /**
//     * 毫秒内自增位
//     */
//    private final long sequenceBits = 12L;
//    /**
//     * 毫秒内最大并发值11111111111 -> 4095
//     */
//    private final long sequenceMask = -1L ^ (-1L << sequenceBits);
//
//    /**
//     * workerId左移位数12
//     */
//    private final long workerIdShift = sequenceBits;
//    /**
//     * datacenterId左移位数17
//     */
//    private final long datacenterIdShift = sequenceBits + workerIdBits;
//    /**
//     * 时间戳左移动位22
//     */
//    private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
//
//
//    private long workerId;
//
//    /**
//     * 数据标识id部分
//     */
//    private long datacenterId;
//    /**
//     * 并发控制
//     */
//    private long sequence = 0L;
//    /**
//     * 上次生产id时间戳
//     */
//    private long lastTimestamp = -1L;
//
//    public GhostKeyGenerator() {
//        this.datacenterId = getDatacenterId(maxDatacenterId);
//        this.workerId = getMaxWorkerId(datacenterId, maxWorkerId);
//    }
//
//    /**
//     * @param workerId     工作机器ID
//     * @param datacenterId 序列号
//     */
//    public GhostKeyGenerator(long workerId, long datacenterId) {
//        if (workerId > maxWorkerId || workerId < 0) {
//            throw new ShardingRuntimeException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
//        }
//        if (datacenterId > maxDatacenterId || datacenterId < 0) {
//            throw new ShardingRuntimeException(
//                    String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
//        }
//        this.workerId = workerId;
//        this.datacenterId = datacenterId;
//    }
//
//    /**
//     * <p>
//     * 获取 maxWorkerId
//     * </p>
//     */
//    private static long getMaxWorkerId(long datacenterId, long maxWorkerId) {
//        StringBuilder mpid = new StringBuilder();
//        mpid.append(datacenterId);
//        String name = ManagementFactory.getRuntimeMXBean().getName();
//        if (StringUtils.isNotEmpty(name)) {
//            /*
//             * GET jvmPid
//             */
//            mpid.append(name.split("@")[0]);
//        }
//        /*
//         * MAC + PID 的 hashcode 获取16个低位
//         */
//        return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1);
//    }
//
//    /**
//     * <p>
//     * 数据标识id部分
//     * </p>
//     */
//    private static long getDatacenterId(long maxDatacenterId) {
//        long id = 0L;
//        try {
//            InetAddress ip = InetAddress.getLocalHost();
//            NetworkInterface network = NetworkInterface.getByInetAddress(ip);
//            if (network == null) {
//                id = 1L;
//            } else {
//                byte[] mac = network.getHardwareAddress();
//                if (null != mac) {
//                    id = ((0x000000FF & (long) mac[mac.length - 1]) | (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6;
//                    id = id % (maxDatacenterId + 1);
//                }
//            }
//        } catch (Exception e) {
//            logger.warn(" getDatacenterId: " + e.getMessage());
//        }
//        return id;
//    }
//
//    /**
//     * 获取下一个ID
//     *
//     * @return
//     */
//    @Override
//    public synchronized Number generateKey() {
//        long timestamp = timeGen();
//        if (timestamp < lastTimestamp) {//闰秒
//            long offset = lastTimestamp - timestamp;
//            if (offset <= 5) {
//                try {
//                    wait(offset << 1);
//                    timestamp = timeGen();
//                    if (timestamp < lastTimestamp) {
//                        throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", offset));
//                    }
//                } catch (Exception e) {
//                    throw new RuntimeException(e);
//                }
//            } else {
//                throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", offset));
//            }
//        }
//
//        if (lastTimestamp == timestamp) {
//            // 相同毫秒内，序列号自增
//            sequence = (sequence + 1) & sequenceMask;
//            if (sequence == 0) {
//                // 同一毫秒的序列数已经达到最大
//                timestamp = tilNextMillis(lastTimestamp);
//            }
//        } else {
//            // 不同毫秒内，序列号置为 1 - 3 随机数
//            sequence = ThreadLocalRandom.current().nextLong(1, 3);
//        }
//
//        lastTimestamp = timestamp;
//
//        if (logger.isDebugEnabled()) {
//            logger.debug("timestamp:{},datacenterId:{},workerId:{},sequence:{}", timestamp, datacenterId, workerId, sequence);
//        }
//
//        return ((timestamp - EPOCH) << timestampLeftShift)    // 时间戳部分
//                | (datacenterId << datacenterIdShift)           // 数据标识部分
//                | (workerId << workerIdShift)                   // 机器标识部分
//                | sequence;                                     // 序列号部分
//    }
//
//    private long tilNextMillis(long lastTimestamp) {
//        long timestamp = timeGen();
//        while (timestamp <= lastTimestamp) {
//            timestamp = timeGen();
//        }
//        return timestamp;
//    }
//
//    private long timeGen() {
//        return SystemClock.now();
//    }
}
